home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / Ang261Lib.lha / src / store1.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  15KB  |  535 lines

  1. /*
  2.  * store1.c: store code, updating store inventory, pricing objects 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include "constant.h"
  12. #include "config.h"
  13. #include "types.h"
  14. #include "externs.h"
  15.  
  16. #ifdef USG
  17. #ifndef ATARIST_MWC
  18. #include <string.h>
  19. #endif
  20. #else
  21. #include <strings.h>
  22. #endif
  23.  
  24. #ifndef NO_LINT_ARGS
  25. #ifdef __STDC__
  26. static void special_offer(inven_type *);
  27. static void insert_store(int, int, int32, struct inven_type *);
  28. static void store_create(int);
  29. #else
  30. static void special_offer();
  31. static void insert_store();
  32. static void store_create();
  33. #endif
  34. #endif
  35.  
  36. /* Returns the value for any given object        -RAK-     */
  37. int32 
  38. item_value(i_ptr)
  39. register inven_type *i_ptr;
  40. {
  41.     register int32      value;
  42.  
  43.     value = i_ptr->cost;
  44. /* don't purchase known cursed items */
  45.     if (i_ptr->ident & ID_DAMD)
  46.     value = 0;
  47.         /* Weapons and armor     */
  48.     else if (((i_ptr->tval >= TV_BOW) && (i_ptr->tval <= TV_SWORD)) ||
  49.          ((i_ptr->tval >= TV_BOOTS) && (i_ptr->tval <= TV_SOFT_ARMOR))) {
  50.     if (!known2_p(i_ptr))
  51.         value = object_list[i_ptr->index].cost;
  52.     else if ((i_ptr->tval >= TV_BOW) && (i_ptr->tval <= TV_SWORD)) {
  53.         if (i_ptr->tohit < 0)
  54.         value = 0;
  55.         else if (i_ptr->todam < 0)
  56.         value = 0;
  57.         else if (i_ptr->toac < 0)
  58.         value = 0;
  59.         else
  60.         value = i_ptr->cost + (i_ptr->tohit + i_ptr->todam + i_ptr->toac) * 100;
  61.     } else {
  62.         if (i_ptr->toac < 0)
  63.         value = 0;
  64.         else
  65.         value = i_ptr->cost + i_ptr->toac * 100;
  66.     }
  67.     } else if (((i_ptr->tval >= TV_SLING_AMMO) && (i_ptr->tval <= TV_ARROW))
  68.            || (i_ptr->tval == TV_SPIKE)) {    /* Ammo             */
  69.     if (!known2_p(i_ptr))
  70.         value = object_list[i_ptr->index].cost;
  71.     else {
  72.         if (i_ptr->tohit < 0)
  73.         value = 0;
  74.         else if (i_ptr->todam < 0)
  75.         value = 0;
  76.         else if (i_ptr->toac < 0)
  77.         value = 0;
  78.         else
  79.  
  80.         /* use 5, because missiles generally appear in groups of 20, so
  81.          * 20 * 5 == 100, which is comparable to weapon bonus above 
  82.          */
  83.         value = i_ptr->cost + (i_ptr->tohit + i_ptr->todam + i_ptr->toac) * 5;
  84.     }
  85.                 /* Potions, Scrolls, and Food */
  86.     } else if ((i_ptr->tval == TV_SCROLL1) || (i_ptr->tval == TV_SCROLL2) ||
  87.            (i_ptr->tval == TV_POTION1) || (i_ptr->tval == TV_POTION2)) {
  88.     if (!known1_p(i_ptr))
  89.         value = 20;
  90.     } else if (i_ptr->tval == TV_FOOD) {
  91.     if ((i_ptr->subval < (ITEM_SINGLE_STACK_MIN + MAX_MUSH))
  92.         && !known1_p(i_ptr))
  93.         value = 1;
  94.                 /* Rings and amulets */
  95.     } else if ((i_ptr->tval == TV_AMULET) || (i_ptr->tval == TV_RING)) {
  96.     /* player does not know what type of ring/amulet this is */
  97.     if (!known1_p(i_ptr))
  98.         value = 45;
  99.     else if (!known2_p(i_ptr))
  100.     /* player knows what type of ring, but does not know whether it is
  101.      * cursed or not, if refuse to buy cursed objects here, then player
  102.      * can use this to 'identify' cursed objects 
  103.      */
  104.         value = object_list[i_ptr->index].cost;
  105.                 /* Wands and staffs */
  106.     } else if ((i_ptr->tval == TV_STAFF) || (i_ptr->tval == TV_WAND)) {
  107.     if (!known1_p(i_ptr)) {
  108.  
  109.         if (i_ptr->tval == TV_WAND)
  110.         value = 50;
  111.         else
  112.         value = 70;
  113.     } else if (known2_p(i_ptr))
  114.         value = i_ptr->cost + (i_ptr->cost / 20) * i_ptr->p1;
  115.     }
  116.                 /* picks and shovels */
  117.     else if (i_ptr->tval == TV_DIGGING) {
  118.     if (!known2_p(i_ptr))
  119.         value = object_list[i_ptr->index].cost;
  120.     else {
  121.         if (i_ptr->p1 < 0)
  122.         value = 0;
  123.         else {
  124.  
  125.         /* some digging tools start with non-zero p1 values, so only
  126.          * multiply the plusses by 100, make sure result is positive 
  127.          * no longer; have adjusted costs in treasure.c -CWS
  128.          */
  129.         value = i_ptr->cost + i_ptr->p1;
  130.         if (value < 0)
  131.             value = 0;
  132.         }
  133.     }
  134.     }
  135. /* multiply value by number of items if it is a group stack item */
  136.     if (i_ptr->subval > ITEM_GROUP_MIN)    /* do not include torches here */
  137.     value = value * i_ptr->number;
  138.     return (value);
  139. }
  140.  
  141.  
  142. /* Asking price for an item                -RAK-     */
  143. int32 
  144. sell_price(snum, max_sell, min_sell, item)
  145.     int                 snum;
  146.     int32              *max_sell, *min_sell;
  147.     inven_type         *item;
  148. {
  149.     register int32      i;
  150.     register store_type *s_ptr;
  151.  
  152.     s_ptr = &store[snum];
  153.     i = item_value(item);
  154. /* check item->cost in case it is cursed, check i in case it is damaged */
  155.     if ((item->cost > 0) && (i > 0)) {
  156.     i = i * rgold_adj[owners[s_ptr->owner].owner_race][py.misc.prace] / 100;
  157.     if (i < 1)
  158.         i = 1;
  159.     *max_sell = i * owners[s_ptr->owner].max_inflate / 100;
  160.     *min_sell = i * owners[s_ptr->owner].min_inflate / 100;
  161.     if (snum == 6) {
  162.         (*max_sell) *= 2;
  163.         (*min_sell) *= 2;
  164.     }
  165.     if (*min_sell > *max_sell)
  166.         *min_sell = *max_sell;
  167.     return (i);
  168.     } else
  169.     /* don't let the item get into the store inventory */
  170.     return (0);
  171. }
  172.  
  173.  
  174. /* Check to see if he will be carrying too many objects    -RAK-     */
  175. int 
  176. store_check_num(t_ptr, store_num)
  177.     inven_type         *t_ptr;
  178.     int                 store_num;
  179. {
  180.     register int        store_check, i;
  181.     register store_type *s_ptr;
  182.     register inven_type *i_ptr;
  183.  
  184.     store_check = FALSE;
  185.     s_ptr = &store[store_num];
  186.     if (s_ptr->store_ctr < STORE_INVEN_MAX)
  187.     store_check = TRUE;
  188.     else if (t_ptr->subval >= ITEM_SINGLE_STACK_MIN)
  189.     for (i = 0; i < s_ptr->store_ctr; i++) {
  190.         i_ptr = &s_ptr->store_inven[i].sitem;
  191.  
  192.     /* note: items with subval of gte ITEM_SINGLE_STACK_MAX only stack if
  193.      * their subvals match 
  194.      */
  195.         if (i_ptr->tval == t_ptr->tval && i_ptr->subval == t_ptr->subval
  196.         && ((int)i_ptr->number + (int)t_ptr->number < 256)
  197.         && (t_ptr->subval < ITEM_GROUP_MIN
  198.             || (i_ptr->p1 == t_ptr->p1)))
  199.         store_check = TRUE;
  200.     }
  201.  
  202. /* But, wait.  If at home, don't let player drop 25th item, or he will lose it. -CFT */
  203.     if (is_home && (t_ptr->subval >= ITEM_SINGLE_STACK_MIN))
  204.     for (i = 0; i < s_ptr->store_ctr; i++) {
  205.         i_ptr = &s_ptr->store_inven[i].sitem;
  206.     /*
  207.      * note: items with subval of gte ITEM_SINGLE_STACK_MAX only stack if
  208.      * their subvals match 
  209.      */
  210.         if (i_ptr->tval == t_ptr->tval && i_ptr->subval == t_ptr->subval
  211.         && ((int)i_ptr->number + (int)t_ptr->number > 24)
  212.         && (t_ptr->subval < ITEM_GROUP_MIN
  213.             || (i_ptr->p1 == t_ptr->p1)))
  214.         store_check = FALSE;
  215.     }
  216.     return (store_check);
  217. }
  218.  
  219.  
  220. /* Insert INVEN_MAX at given location     */
  221. static void 
  222. insert_store(store_num, pos, icost, i_ptr)
  223.     register int        pos;
  224.     int                 store_num;
  225.     int32               icost;
  226.     inven_type         *i_ptr;
  227. {
  228.     register int        i;
  229.     register store_type *s_ptr;
  230.  
  231.     s_ptr = &store[store_num];
  232.     for (i = s_ptr->store_ctr - 1; i >= pos; i--)
  233.     s_ptr->store_inven[i + 1] = s_ptr->store_inven[i];
  234.     s_ptr->store_inven[pos].sitem = *i_ptr;
  235.     s_ptr->store_inven[pos].scost = (-icost);
  236.     s_ptr->store_ctr++;
  237. }
  238.  
  239.  
  240. /* Add the item in INVEN_MAX to stores inventory.    -RAK-     */
  241. void 
  242. store_carry(store_num, ipos, t_ptr)
  243.     int                 store_num;
  244.     int                *ipos;
  245.     inven_type         *t_ptr;
  246. {
  247.     int                 item_num, item_val, flag;
  248.     register int        typ, subt;
  249.     int32               icost, dummy;
  250.     register inven_type *i_ptr;
  251.     register store_type *s_ptr;
  252.     int stacked = FALSE; /* from inven_carry() -CFT */
  253.  
  254.     *ipos = -1;
  255.     if (sell_price(store_num, &icost, &dummy, t_ptr) > 0 || is_home)
  256.     {
  257.     s_ptr = &store[store_num];
  258.     item_val = 0;
  259.     item_num = t_ptr->number;
  260.     flag = FALSE;
  261.     typ  = t_ptr->tval;
  262.     subt = t_ptr->subval;
  263.     if (subt >= ITEM_SINGLE_STACK_MIN) { /* try to stack in store's inven */
  264.         do {
  265.         i_ptr = &s_ptr->store_inven[item_val].sitem;
  266.         if (typ == i_ptr->tval)
  267.         {
  268.             if (subt == i_ptr->subval && /* Adds to other item        */
  269.             subt >= ITEM_SINGLE_STACK_MIN
  270.             && (subt < ITEM_GROUP_MIN || i_ptr->p1 == t_ptr->p1))
  271.             {
  272.             stacked = TRUE; /* remember that we did stack it... -CFT */
  273.             *ipos = item_val;
  274.             i_ptr->number += item_num;
  275.             /* must set new scost for group items, do this only for items
  276.                strictly greater than group_min, not for torches, this
  277.                must be recalculated for entire group */
  278.             if (subt > ITEM_GROUP_MIN)
  279.             {
  280.                 (void) sell_price (store_num, &icost, &dummy, i_ptr);
  281.                 s_ptr->store_inven[item_val].scost = -icost;
  282.             }
  283.             /* must let group objects (except torches) stack over 24
  284.                since there may be more than 24 in the group */
  285.             else if (i_ptr->number > 24)
  286.                 i_ptr->number = 24;
  287.             flag = TRUE;
  288.             }
  289.         }
  290.         item_val ++;
  291.         } while (!stacked && (item_val < s_ptr->store_ctr));
  292.     } /* if might stack... -CFT */
  293.     if (!stacked) {        /* either never stacks, or didn't find a place to stack */
  294.         item_val = 0;
  295.         do {
  296.         i_ptr = &s_ptr->store_inven[item_val].sitem;
  297.         if ((typ > i_ptr->tval) || /* sort by desc tval, */
  298.             ((typ == i_ptr->tval) &&
  299.              ((t_ptr->level < i_ptr->level) || /* then by inc level, */
  300.               ((t_ptr->level == i_ptr->level) &&
  301.                (subt < i_ptr->subval))))) /* and finally by inc subval -CFT */
  302.         {        /* Insert into list             */
  303.             insert_store(store_num, item_val, icost, t_ptr);
  304.             flag = TRUE;
  305.             *ipos = item_val;
  306.         }
  307.         item_val++;
  308.         } while ((item_val < s_ptr->store_ctr) && (!flag));
  309.     } /* if didn't already stack it... */
  310.     if (!flag)        /* Becomes last item in list    */
  311.     {
  312.         insert_store(store_num, (int)s_ptr->store_ctr, icost, t_ptr);
  313.         *ipos = s_ptr->store_ctr - 1;
  314.     }
  315.     }
  316. }
  317.  
  318.  
  319. /* Destroy an item in the stores inventory.  Note that if     */
  320. /* "one_of" is false, an entire slot is destroyed    -RAK-     */
  321. void 
  322. store_destroy(store_num, item_val, one_of)
  323. int store_num, item_val;
  324. int one_of;
  325. {
  326.     register int         j, number;
  327.     register store_type *s_ptr;
  328.     register inven_type *i_ptr;
  329.  
  330.     s_ptr = &store[store_num];
  331.     i_ptr = &s_ptr->store_inven[item_val].sitem;
  332.  
  333. /* for single stackable objects, only destroy one half on average, this will
  334.  * help ensure that general store and alchemist have reasonable selection of
  335.  * objects 
  336.  */
  337.     if ((i_ptr->subval >= ITEM_SINGLE_STACK_MIN) &&
  338.     (i_ptr->subval <= ITEM_SINGLE_STACK_MAX)) {
  339.     if (one_of)
  340.         number = 1;
  341.     else
  342.         number = randint((int)i_ptr->number);
  343.     } else
  344.     number = i_ptr->number;
  345.  
  346.     if (number != i_ptr->number)
  347.     i_ptr->number -= number;
  348.     else {
  349.     for (j = item_val; j < s_ptr->store_ctr - 1; j++)
  350.         s_ptr->store_inven[j] = s_ptr->store_inven[j + 1];
  351.     invcopy(&s_ptr->store_inven[s_ptr->store_ctr - 1].sitem, OBJ_NOTHING);
  352.     s_ptr->store_inven[s_ptr->store_ctr - 1].scost = 0;
  353.     s_ptr->store_ctr--;
  354.     }
  355. }
  356.  
  357.  
  358. /* Initializes the stores with owners            -RAK-     */
  359. void 
  360. store_init()
  361. {
  362.     register int         i, j, k;
  363.     register store_type *s_ptr;
  364.  
  365.     i = MAX_OWNERS / MAX_STORES;
  366.     for (j = 0; j < MAX_STORES; j++) {
  367.     s_ptr = &store[j];
  368.     s_ptr->owner = MAX_STORES * (randint(i) - 1) + j;
  369.     s_ptr->insult_cur = 0;
  370.     s_ptr->store_open = 0;
  371.     s_ptr->store_ctr = 0;
  372.     s_ptr->good_buy = 0;
  373.     s_ptr->bad_buy = 0;
  374.     for (k = 0; k < STORE_INVEN_MAX; k++) {
  375.         invcopy(&s_ptr->store_inven[k].sitem, OBJ_NOTHING);
  376.         s_ptr->store_inven[k].scost = 0;
  377.     }
  378.     }
  379. }
  380.  
  381.  
  382. /* Creates an item and inserts it into store's inven    -RAK-     */
  383. static void 
  384. store_create(store_num)
  385. int store_num;
  386. {
  387.     register int         i, tries;
  388.     int                  cur_pos, dummy;
  389.     register store_type *s_ptr;
  390.     register inven_type *t_ptr;
  391.  
  392.     tries = 0;
  393.     cur_pos = popt();
  394.     s_ptr = &store[store_num];
  395.     object_level = OBJ_TOWN_LEVEL;
  396.     do {
  397.     if (store_num != 6) {
  398.         i = store_choice[store_num][randint(STORE_CHOICES) - 1];
  399.         invcopy(&t_list[cur_pos], i);
  400.         magic_treasure(cur_pos, OBJ_TOWN_LEVEL, FALSE, TRUE);
  401.         t_ptr = &t_list[cur_pos];
  402.         if (store_check_num(t_ptr, store_num)) {
  403.         if ((t_ptr->cost > 0) &&    /* Item must be good     */
  404.             (t_ptr->cost < owners[s_ptr->owner].max_cost)) {
  405.  
  406. /* equivalent to calling ident_spell(), except will not change the object_ident array */
  407.             store_bought(t_ptr);
  408.             special_offer(t_ptr);
  409.             store_carry(store_num, &dummy, t_ptr);
  410.             tries = 10;
  411.         }
  412.         }
  413.         tries++;
  414.     } else {
  415.         i = get_obj_num(40, FALSE);
  416.         invcopy(&t_list[cur_pos], i);
  417.         magic_treasure(cur_pos, 40, FALSE, TRUE);
  418.         t_ptr = &t_list[cur_pos];
  419.         if (store_check_num(t_ptr, store_num)) {
  420.         if (t_ptr->cost > 0) {    /* Item must be good     */
  421.         /*
  422.          * equivalent to calling ident_spell(), except will not
  423.          * change the object_ident array 
  424.          */
  425.             store_bought(t_ptr);
  426.             special_offer(t_ptr);
  427.             store_carry(store_num, &dummy, t_ptr);
  428.             tries = 10;
  429.         }
  430.         }
  431.         tries++;
  432.     }
  433.     }
  434.     while (tries <= 3);
  435.     pusht(cur_pos);
  436. }
  437.  
  438. static void 
  439. special_offer(i_ptr)
  440. inven_type *i_ptr;
  441. {
  442.     int32 orig_cost = i_ptr->cost;
  443.  
  444.     if (randint(30) == 1) {
  445.     i_ptr->cost = (i_ptr->cost * 3) / 4;
  446.     if (i_ptr->cost < 1)
  447.         i_ptr->cost = 1;
  448.     if (i_ptr->cost < orig_cost)
  449.         inscribe(i_ptr, "25% discount");
  450.     } else if (randint(150) == 1) {
  451.     i_ptr->cost /= 2;
  452.     if (i_ptr->cost < 1)
  453.         i_ptr->cost = 1;
  454.     if (i_ptr->cost < orig_cost)
  455.         inscribe(i_ptr, "50% discount");
  456.     } else if (randint(300) == 1) {
  457.     i_ptr->cost /= 4;
  458.     if (i_ptr->cost < 1)
  459.         i_ptr->cost = 1;
  460.     if (i_ptr->cost < orig_cost)
  461.         inscribe(i_ptr, "75% discount");
  462.     } else if (randint(500) == 1) {
  463.     i_ptr->cost /= 10;
  464.     if (i_ptr->cost < 1)
  465.         i_ptr->cost = 1;
  466.     if (i_ptr->cost < orig_cost)
  467.         inscribe(i_ptr, "to clear");
  468.     }
  469. }
  470.  
  471. /* Initialize and up-keep the store's inventory.        -RAK-     */
  472. void 
  473. store_maint()
  474. {
  475.     register int         i, j;
  476.     register store_type *s_ptr;
  477.  
  478.     for (i = 0; i < (MAX_STORES - 1); i++) {
  479.     s_ptr = &store[i];
  480.     s_ptr->insult_cur = 0;
  481.     if (s_ptr->store_ctr >= STORE_MIN_INVEN) {
  482.         j = randint(STORE_TURN_AROUND);
  483.         if (s_ptr->store_ctr >= STORE_MAX_INVEN)
  484.         j += 1 + s_ptr->store_ctr - STORE_MAX_INVEN;
  485.         while (--j >= 0)
  486.         store_destroy(i, randint((int)s_ptr->store_ctr) - 1, FALSE);
  487.     }
  488.     if (s_ptr->store_ctr <= STORE_MAX_INVEN) {
  489.         j = randint(STORE_TURN_AROUND);
  490.         if (s_ptr->store_ctr < STORE_MIN_INVEN)
  491.         j += STORE_MIN_INVEN - s_ptr->store_ctr;
  492.         while (--j >= 0)
  493.         store_create(i);
  494.     }
  495.     }
  496. }
  497.  
  498. /* eliminate need to bargain if player has haggled well in the past   -DJB- */
  499. int 
  500. noneedtobargain(store_num, minprice)
  501. int store_num;
  502. int32 minprice;
  503. {
  504.     register int         flagnoneed;
  505.     register store_type *s_ptr;
  506.  
  507.     if (no_haggle_flag)
  508.     return (TRUE);
  509.  
  510.     s_ptr = &store[store_num];
  511.     flagnoneed = ((s_ptr->good_buy == MAX_SHORT)
  512.           || ((s_ptr->good_buy - 3 * s_ptr->bad_buy) > (5 + (minprice/50))));
  513.     return (flagnoneed);
  514. }
  515.  
  516.  
  517. /* update the bargin info                    -DJB- */
  518. void 
  519. updatebargain(store_num, price, minprice)
  520. int   store_num;
  521. int32 price, minprice;
  522. {
  523.     register store_type *s_ptr;
  524.  
  525.     s_ptr = &store[store_num];
  526.     if (minprice > 9)
  527.     if (price == minprice) {
  528.         if (s_ptr->good_buy < MAX_SHORT)
  529.         s_ptr->good_buy++;
  530.     } else {
  531.         if (s_ptr->bad_buy < MAX_SHORT)
  532.         s_ptr->bad_buy++;
  533.     }
  534. }
  535.